use std::io; //Shtuchki ot Ivashki (c), v0.8.3_a, 2023.
use ferris_says::say; // ДОБАВИТЬ ПРОВЕРКУ СОБСТ/НАР
use scraper::{Html, Selector};
use reqwest::blocking::get;

fn main() {
    println!("Помощь с морфологическим разбором! Нажмите ctrl + c чтобы выйти,  введите '//' для сжатой справки. Не вводите инфинитив!!!.");
    let mut flag = true;
    while flag{
        println!("Bведите слово (не вводите инфинитив!!!): ");
        let mut ur = String::from("https://udarenieru.ru/index.php?forma=");
        let mut inp_s = String::new();
        let mut narr = false;
        io::stdin().read_line(&mut inp_s).unwrap(); // ДОБАВИТЬ ФУНКЦИОНАЛ ДЛЯ ЧТЕНИЯ ЧЕРЕЗ LOCK()
        inp_s = inp_s.trim_end().to_owned();
        /*if inp_s == "хва"{
            flag = false;
            continue;
        }*/
        if inp_s == "//" {
            let stdout = io::stdout();
            let message = String::from("Небольшая справка:\n1) Если программa вылетает, значит либо она не находит слово в словарях, либо вы допустили ошибку. \n2) Если вам вместе и падежом попалась приписка (одуш.), то не обращайте на неё внимание. \n3) Не вводите инфинитивы!!! Для них программа не сможет предоставить разбор. \n4) Это программа-эксперимент! Не стоит использовать её результаты. \n5) Телеграм разработчика(для вопросов и предложений): @iVanSFrolov");
            let width = message.chars().count();

            let mut writer = io::BufWriter::new(stdout.lock());
            say(&message, width, &mut writer).unwrap();
            //flag = false;
            continue;
        }
        else if inp_s.ends_with("о"){
            println!("Осторожно, возможно это слово категории состояния, для него разбор может быть предоставлен некорректно!");
            narr = true;
        }

        ur += &inp_s;

        let mut info = String::new();
        let mut info_inf = String::new();
        let mut info_con = vec![];
        //let mut mul_unc = vec![];
        let mut info_unc = vec![];
        let mut all_uncs = vec![];
        let mut counter = 0;
        let mut inff = String::new();
        let mut info_inf_m = String::new();
        let mut is_pr = vec![];
        let mut is_de = vec![];
        let mut mm = false;
        let mut morph = false;
        let mut leave = false;
        let mut mc = false; // много разных слов
        println!("Отправляю запрос...");
        let response = get(ur).expect("Не удалось получить ответ");
        println!("Получил ответ...");
        let body = response.text().expect("Не удалось получить тело ответа");

        let document = Html::parse_document(&body);
        let selector =  Selector::parse("i").expect("ничего не найдено");
        //info = document.select(&selector).next().expect("").text().collect::<String>();
        for element in document.select(&selector) { 
                info = element.text().collect::<String>();
                //println!(" 2 {}",info); //РАСКОММЕНТ!!!
        }
        if info.starts_with("Словарной статьи") {
            let mut url_inf = String::from("https://udarenieru.ru/index.php?doc=");
            url_inf += &inp_s;
            let response_inf = get(url_inf).expect("Не удалось получить ответ");
            let bodyinf = response_inf.text().expect("Не удалось получить тело ответа");
            let document_inf = Html::parse_document(&bodyinf);
            let selector_inf =  Selector::parse("i").expect("ничего не найдено");
            for element_i in document_inf.select(&selector_inf) {
    
                info_inf = element_i.text().collect::<String>();
                break;
            }

            //println!(" 3 {:?}",info_inf); //РАСКОММЕНТ!!!
            info_con = info_inf.split(',').collect();
        }
        if info == ""{ // если слово не инфинитив
            let selector =  Selector::parse("p").expect("ничего не найдено");

            for element in document.select(&selector) {
        
                info = element.text().collect::<String>();
                //println!(" не то {}", &info); //РАСКОММЕНТ!!!
                all_uncs.push(info.clone());
            }
            if all_uncs.len() > 1{
                mm = true;
            }
            //println!("{:#?}",all_uncs);
            for info in all_uncs{
                let mut mul_unc = vec![];
            if info.starts_with("Словарной статьи") {
                let mut url_inf = String::from("https://udarenieru.ru/index.php?word=on&morph_word=");
                url_inf += &inp_s;
                let response_inf = get(url_inf).expect("Не удалось получить ответ");
                let bodyinf = response_inf.text().expect("Не удалось получить тело ответа");
                let document_inf = Html::parse_document(&bodyinf);
                let selector_inf =  Selector::parse("td").expect("ничего не найдено");
                for element_i in document_inf.select(&selector_inf) {
        
                    info_inf = element_i.text().collect::<String>();
                    //leave = true;
                    //println!("3 {}", &info_inf);
                    break;
                }
                if info_inf.contains("нареч."){
                    //narr = true;
                    nar(&inp_s);
                    continue;
                }else{
                    println!("Ошибочка!");
                    continue;
                }
                
            }
            let a = info.clone();
            if info.contains(";"){
                if !morph{
                    let st = a.find("в").expect("как такая ошибка вообще могла случиться ??!!!");
                    mul_unc = a[st..].split(";").collect();
                }else{
                    let st = a.find("[").expect("как такая ошибка вообще могла случиться ??!!!");
                    let fin = a.find("]").expect("как такая ошибка вообще могла случиться ??!!!");
                    mul_unc = a[st..fin+2].split(";").collect();
                }
                morph = false;
                mm = true;
            }else{
                mul_unc.push(&a);
            }
            let lst = mul_unc[mul_unc.len()-1];
            //println!(" 0 {:#?}", mul_unc);
            info_unc = info.split(',').collect();
            
            let st_inf = info_unc[info_unc.len()-1].rfind("«").expect("ошибка!");
            //println!("{}",st_inf);
            let fin_inf = info_unc[info_unc.len()-1].rfind("»").expect("ошибка! такое слово нельзя просклонять.");
            //println!("{}",fin_inf); 
            inff = String::from(&info_unc[info_unc.len()-1][st_inf+2..fin_inf]);
            //println!("{}", inff);
            let mut url_inf = String::from("https://udarenieru.ru/index.php?doc=");
            url_inf += &inff;
            let response_inf = get(url_inf).expect("Не удалось получить ответ");
            let bodyinf = response_inf.text().expect("Не удалось получить тело ответа");
            let document_inf = Html::parse_document(&bodyinf);
            let selector_inf =  Selector::parse("i").expect("ничего не найдено");
            let selector_inf_for_m =  Selector::parse("p").expect("ничего не найдено");
            for element_i in document_inf.select(&selector_inf) {
    
                info_inf = element_i.text().collect::<String>();
                break;
            }
            if info_inf == "местоимение"{
                
                for element_i in document_inf.select(&selector_inf_for_m) {
    
                    info_inf_m = element_i.text().collect::<String>();
                   // break;
            }
            }
            
            //println!("{:?} type: {}",info_inf, info_inf_m); //РАСКОММЕНТ!!!
            info_con = info_inf.split(',').collect();

            counter = 0;

            if mm{println!("Найдено несколько вариантов разбора!\n");}
            for infoo in mul_unc{

            //println!("{:#?},{:#?}",info_con, &infoo);
            is_pr.push(false);
            is_de.push(false);
            info_unc = infoo.split(',').collect();
            if info_unc[0].contains("прич."){
                is_pr[counter] = true;
            }
            else if info_unc[0].contains("деепр."){
                is_de[counter] = true;
            }
            let raws = String::from(infoo);
            if info_unc.len() != 0{
                if !is_de[counter] && !is_pr[counter]{
                    match info_con[0]{
                        "прилагательное" => pril(&info_con, &inp_s, &inff, &info_unc, mm, &raws),
                        "глагол" => glag(&info_con, &inp_s, &inff, &info_unc, mm), 
                        "существительное" => sush(&info_con, &inp_s, &inff, &info_unc, mm),     
                        "причастие" => prich(&info_con, &inp_s, &inff, &info_unc),
                        "местоимение" => mest(&info_con, &inp_s, &inff, &info_unc, &info_inf_m),
                        //"числительное" => println!("ДЛЯ ЧИСЛИТЕЛЬНОГО НЕ МОГУ ПРЕДОСТАВИТЬ РАЗБОР, НО МОГУ ДАТЬ ПЛАН: 1) {} - числительное, обозначает число или порядок при счёте. \n 2) Начальная форма: {} \n 3) Постоянные признаки: количественное или порядковое,\n целое число, дробное или собирательное,\n простое, сложное или составное .\n 4)Непостоянные  признаки: род, число, падеж\n 5) Может являться любым членом предложения.", &inp_s,&inff), //,con[3],unc[unc.len()-3],con[1],unc[unc.len()-2]);                        ,

        
                        &_ => {if narr{
                            println!("Это наречие или слово категории состояния. Я не могу предоставить разбор, поэтому вот план:\n");
                            nar(&inp_s);
                        }
                        else {
                            println!("Ошибка! Невозможно определить часть речи и предоставить разбор!");
                        }

                        },
                    }
                }
                else if is_pr[counter]{
                    prich(&info_con, &inp_s, &inff, &info_unc);
                }
                else if is_de[counter]{
                    deprich(&info_con, &inp_s, &inff, &info_unc);
                }
                
            } else {
                info_con.reverse();
                info_con.pop();
                println!("Вы ввели инфинитив. Такое не приветствуется, поэтому вот его постоянные признаки(если ничего нет, то информация не найдена): "); // ТУДУ! {:#?}
                for el in &info_con{
                    println!("{}",el);           
                }
                println!("Может являться любым членом предложения.");
                continue;
            }
            info_unc.clear();
            counter+=1;
            println!("-------------------------------------");
            //if infoo == lst{mul_unc.clear();break;}
        }
       // mul_unc.clear();
        info_con.clear();
    }
        }

        
            
        else { //else
            info_con = info.split(',').collect();
            println!("непредвиденная ошибка! ");
        }

       //println!("{:#?},{:#?}",info_con,info_unc); //РАСКОММЕНТ!!! // Короче, разделять непост пр по дв. точиям, соотвестственно info_unc будет вестором из весторов, и в матче просто через фор каждый вестор прогонять.
    
      // counter = 0;
       /*for info in &mul_unc{
        info_unc = info.split(',').collect();
        all_uncs[counter] = info_unc.clone();
        if info_unc[0].ends_with("форма в прич."){
            is_pr[counter] = true;
        }
        else if info_unc[0].ends_with("форма в деепр."){
            is_de[counter] = true;
        }
        info_unc.clear();
        counter+=1;
        }*/
       /* if mm{println!("Найдено несколько вариантов разбора!");}
        for info in mul_unc{
            println!("{:#?},{:#?}",info_con, &info);
            is_pr.push(false);
            is_de.push(false);
            info_unc = info.split(',').collect();
            if info_unc[0].contains("прич."){
                is_pr[counter] = true;
            }
            else if info_unc[0].contains("деепр."){
                is_de[counter] = true;
            }
            let raws = String::from(info);
            if info_unc.len() != 0{
                if !is_de[counter] && !is_pr[counter]{
                    match info_con[0]{
                        "прилагательное" => pril(&info_con, &inp_s, &inff, &info_unc, mm, &raws),
                        "глагол" => glag(&info_con, &inp_s, &inff, &info_unc, mm), 
                        "существительное" => sush(&info_con, &inp_s, &inff, &info_unc, mm),     
                        "причастие" => prich(&info_con, &inp_s, &inff, &info_unc),
                        "местоимение" => mest(&info_con, &inp_s, &inff, &info_unc, &info_inf_m),
                        "числительное" => println!("пока не готово..."),
        
                        &_ => println!("Ошибка! Невозможно определить часть речи."),
                    }
                }
                else if is_pr[counter]{
                    prich(&info_con, &inp_s, &inff, &info_unc);
                }
                else if is_de[counter]{
                    deprich(&info_con, &inp_s, &inff, &info_unc);
                }
                
            } else {
                info_con.reverse();
                info_con.pop();
                println!("Вы ввели инфинитив. Такое не приветствуется, поэтому вот его постоянные признаки(если ничего нет, то информация не найдена): "); // ТУДУ! {:#?}
                for el in &info_con{
                    println!("{}",el);           
                }
                println!("Может являться любым членом предложения.");
                continue;
            }
            info_unc.clear();
            counter+=1;
        }*/
        

        

}
}

fn glag(con: &Vec<&str>, inpp: &String , inff: &String ,unc: &Vec<&str>, flag:bool){
    //println!("внутри");
    let nak: Vec<_> = unc[unc.len()-1].split(" от ").collect();
    //println!("1");
    let mut last;
    if flag{
        last = &unc[0][unc[0].find(")").expect(r"неизвестная ошибка. shit happens! ¯\_(ツ)_/¯")+2..];
    }else{
        last = &unc[0][unc[0].rfind("в").expect(r"неизвестная ошибка. shit happens! ¯\_(ツ)_/¯")+2..];
    }
    
    //for(){}
    if nak[0] == " изъявит. накл."{
        if unc[3] == " наст.вр." {
            println!("1) {} - глагол, обозначает действие предмета.\n2) Начальная форма: {} \n3) Пост.пр.: {},{},{},{} \n4) Непост.пр.: {}, {},{},{}", inpp, inff ,con[3], con[1], con[4], con[2], nak[0], unc[3], unc[1], last);
        }else {
            println!("1) {} - глагол, обозначает действие предмета.\n2) Начальная форма: {} \n3) Пост.пр.: {},{},{},{} \n4) Непост.пр.: {}, {},{},{}", inpp, inff ,con[3], con[1], con[4], con[2], nak[0], unc[3], unc[1], last);
        }
    }else if nak[0] == " сослаг.накл. "{
        if unc[1] == " ед.ч"{
            println!("1) {} - глагол, обозначает действие предмета.\n2) Начальная форма: {} \n3) Пост.пр.: {},{},{},{} \n4) Непост.пр.: {},{}", inpp, inff ,con[3], con[1], con[4], con[2], unc[1], last);
        }
        else {
            println!("1) {} - глагол, обозначает действие предмета.\n2) Начальная форма: {} \n3) Пост.пр.: {},{},{},{} \n4) Непост.пр.: {}", inpp, inff ,con[3], con[1], con[4], con[2], unc[1]);
        }
    }else  { // if nak[0] == " повелит. накл. "
        println!("1) {} - глагол, обозначает действие предмета.\n2) Начальная форма: {} \n3) Пост.пр.: {},{},{},{} \n4) Непост.пр.: {}", inpp, inff ,con[3], con[1], con[4], con[2], last);
    }
    println!("5) В предложении является вероятнее всего сказуемым.\n");
    }

fn sush(con: &Vec<&str>, inpp: &String , inff: &String ,unc: &Vec<&str>, flag:bool){
    let mut last;
    if flag{
        last = &unc[0][unc[0].find(")").expect(r"неизвестная ошибка. shit happens! ¯\_(ツ)_/¯")+2..];
    }else{
        last = &unc[0][unc[0].rfind("в").expect(r"неизвестная ошибка. shit happens! ¯\_(ツ)_/¯")+2..];
    }
    //let mut countt = 1;
   // let last = &unc[0][unc[0].rfind("в").expect(r"неизвестная ошибка. shit happens! ¯\_(ツ)_/¯")..];
    let nak: Vec<_> = unc[unc.len()-1].split(" от ").collect();
    println!("1) {} - существительное, обозначает предмет.\n2) Начальная форма: {} \n3) Пост.пр.: собственное или нарицательное, ",inpp, inff);
    for i in 0..con.len()-1{  
        println!("{}", con[i+1]);
    }
    println!("4) Непост.пр.: ");
    for zx in unc{
        println!("{}", zx);
    }
    println!("5) В предложении является неизвестно чем.\n");
}

fn pril(con: &Vec<&str>, inpp: &String , inff: &String ,unc: &Vec<&str>, flag:bool, raw: &String){
    let mut last;
    if flag{
        last = &unc[0][unc[0].find(")").expect(r"неизвестная ошибка. shit happens! ¯\_(ツ)_/¯")+2..];
    }else{
        last = &unc[0][unc[0].rfind("в").expect(r"неизвестная ошибка. shit happens! ¯\_(ツ)_/¯")+2..];
    }
   // let last = &unc[0][unc[0].rfind("в").expect(r"неизвестная ошибка. shit happens! ¯\_(ツ)_/¯")..];
   // println!("{}",last);
    let nak: Vec<_> = unc[unc.len()-1].split(" от ").collect();
    if con[con.len()-1] == " качественное"{
        println!("1) {} - прилагательное, обозначает признак предмета.\n2) Начальная форма: {} \n3) Пост.пр.: качественное \n4) Непост.пр.: сравнительная или превосходная форма, ", inpp, inff);// , unc[2],  last);
        
        //if nak[0].contains("ед.ч"){println!("{}", unc[1]); }
    }else if con[con.len()-1] != "прилагательное"{
        println!("1) {} - прилагательное, обозначает признак предмета.\n2) Начальная форма: {} \n3) Пост.пр.: {} \n4) Непост.пр.: ", inpp, inff , con[1],);
    }

    else if last.contains("кр. ф."){
        println!("1) {} - прилагательное, обозначает признак предмета.\n2) Начальная форма: {} \n3) Пост.пр.: качественное \n4) Непост.пр.: ", inpp, inff,);

    }
    else {
        println!("1) {} - прилагательное, обозначает признак предмета.\n2) Начальная форма: {} \n3) Пост.пр.: относительное,притяжательное или качественное(если в кр.ф) \n4) Непост.пр.: ", inpp, inff);
    }
    for zx in unc{
        println!("{}", zx);
    }
    println!("5) В предложении является неизвестно чем.\n");
    
}

fn prich(con: &Vec<&str>, inpp: &String , inff: &String ,unc: &Vec<&str>){
    //let last = &unc[0][unc[0].rfind("в").expect(r"неизвестная ошибка. shit happens! ¯\_(ツ)_/¯")..];
    //let nak: Vec<_> = unc[unc.len()-1].split(" от ").collect();
    if con.len() > 2{
        println!("1) {} - причастие, обозначает действие-признак.\n2) Образовано от: {}, укажите суффикс причастия! \n3) Пост.пр.: {},{},{},{} \n4) Непост.пр.: ", inpp, inff ,con[3],unc[unc.len()-3],con[1],unc[unc.len()-2]);
        if unc[unc.len()-3].contains("страд. залог"){
            println!("полная или кратакая форма,")
        }
        for ele in 1..unc.len()-3{
            println!("{}",unc[ele]);
        }
            println!("5) В предложении является вероятнее всего определением.\n");
    }
    else {
        println!("[Разбор недоступен]");
    }
    

}

fn deprich(con: &Vec<&str>, inpp: &String , inff: &String ,_unc: &Vec<&str>){
    //let last = &unc[0][unc[0].rfind("в").expect(r"неизвестная ошибка. shit happens! ¯\_(ツ)_/¯")..];
    //let nak: Vec<_> = unc[unc.len()-1].split(" от ").collect();
    println!("1) {} - деепричастие, обозначает добавочное действие.\n2) Образовано от: {}, укажите суффикс деепричастия! \n3) Морфологические признаки: {}, {}", inpp, inff, con[1], con[3]); //,con[3],unc[unc.len()-3],con[1],unc[unc.len()-2]);
    println!("4) В предложении является вероятнее всего обстоятельством.");
    
}

fn mest(_con: &Vec<&str>, inpp: &String , inff: &String ,unc: &Vec<&str>, inf: &String){
    println!("1) {} - местоимение, указывает на предмет не называя его. \n 2) Начальная форма: {} \n 3) Постоянный признак: {}\n 4)Непостоянные  признаки: ", inpp, inff, inf); //,con[3],unc[unc.len()-3],con[1],unc[unc.len()-2]);
    for ele in unc{
        println!("{}",ele);
    }
    println!("4) В предложении является неизвестно чем.\n");
}

fn nar(inpp: &String ){
   
        println!("1) {} - наречие/слово категории состояния, обозначает признак предмета/признак действия.\n2) Морфологические признаки: \n 1) неизменяемость \n 2) разряд по значению \n 3) степень сравнения.", inpp); //,con[3],unc[unc.len()-3],con[1],unc[unc.len()-2]);
        println!("3) В предложении является обстоятельством или сказуемым (не точно).\n");
}

//fn chis(_con: &Vec<&str>, inpp: &String , inff: &String ,unc: &Vec<&str>, inf: &String){} //TODO!
